package za.org.meraka.chi;

import java.util.List;
import java.util.ArrayList;

import android.os.AsyncTask;

import org.jivesoftware.smack.SmackAndroid;

import android.R.layout;

import android.net.Uri;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;

import android.app.ActionBar;

//
// preference stuff
//
import android.preference.PreferenceManager;
import android.content.SharedPreferences;
import android.preference.PreferenceScreen;
import android.preference.EditTextPreference;
import android.preference.Preference;

import android.content.Intent;

//
// views and widgets
//
import android.view.View;
import android.view.ViewGroup;
import android.view.MenuInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;

import android.util.TypedValue;

import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;

import android.text.method.ScrollingMovementMethod;
import android.text.method.MovementMethod;

import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;

import android.view.GestureDetector;
import android.view.MotionEvent;


//
// this is to initialise the smack xmpp
// library
//
import org.jivesoftware.smack.SmackAndroid;



public class Chi extends Activity implements 
	SharedPreferences.OnSharedPreferenceChangeListener
{
    SmackAndroid smackAndroid;

    //
    // the action bar
    //
    ActionBar actionBar = null;

    //
    // drawables for the action bar
    //
    ColorDrawable workgroupColorDrawable;
    ColorDrawable conferenceColorDrawable;
    ColorDrawable statusColorDrawable;

    Drawable workgroupChatDrawable;
    Drawable conferenceChatDrawable;
    Drawable statusChatDrawable;


    //
    // this holds the user login information
    //
    ChiChatConfig chiChatConfig;

    //
    // This handles all the XMPP stuff, workgroup
    // stuff, and conference stuff
    //
    WorkGroupChat workGroupChat;

    //
    // this indicates which screen is showing
    //
    Boolean groupChatShowing = false;

    //
    // this indicates whether the user is logged
    // in or not
    //
    boolean loggedIn = false;


    //
    // the primary conversation view which scrolls
    //
    EditText conversationView = null;
    MovementMethod scrollingMovementMethod = null;

    //
    // the message the user is typing in
    //
    EditText messageText = null;


    BitmapDrawable bitmapDrawable = null;
    Bitmap bitmap = null;

    StringBuilder growingStatusConversation = new StringBuilder();
    StringBuilder growingGroupConversation = new StringBuilder();
    StringBuilder growingPrivateConversation = new StringBuilder();

    String status = new String();
    String activityResults = new String();

    //
    // Shared Preferences
    //
    SharedPreferences sharedPreferences = null;

    @Override
    protected void onResume() {
	super.onResume();
	sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
	sharedPreferences.registerOnSharedPreferenceChangeListener(this);
    }

    private void setTextSize(String textSize) {
	try {
		float size = new Float(textSize);
		conversationView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 
			size);
		messageText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 
			size);
	}
	catch ( Throwable t ) {
	}
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
	String value = sharedPreferences.getString(key, "testing");

	//
	// this commits it to the SharedPreferences cache
	//
	SharedPreferences.Editor editor = this.sharedPreferences.edit();
	editor.putString(key, value);
	editor.commit();

	//
	// change the font sizes
	//
	if ( key.equals("textSize") ) {
		setTextSize(value);
	}

	//
	// NB:  should log in if the server changes
	//
    }

    //
    // a temporary function for initialsing the ChatConfig
    //
    private void initChiChatConfig(Activity context) {
	sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
	String username = sharedPreferences.getString("username", "unknown");
	String password = sharedPreferences.getString("password", "unknown");
	String nickname = sharedPreferences.getString("nickname", "unknown");
	String server = sharedPreferences.getString("server", "c3to.meraka.csir.co.za");
	String port = sharedPreferences.getString("port", "5222");
	String workgroup = sharedPreferences.getString("workgroup", getString(R.string.workgroup_name));
	String conference = sharedPreferences.getString("workgroup", getString(R.string.conference_name));
	String textSize = sharedPreferences.getString("textSize", "14");

	status = status.concat( " username [" + username + "] password[********] nickname[" +
		nickname + "] server["+ server + "] port[" + port + "] workgroup[" +
		workgroup + "] textSize [" + textSize + "]");


    	chiChatConfig = new ChiChatConfig();
  	chiChatConfig.setUsername(username);
	chiChatConfig.setPassword(password);
	chiChatConfig.setNickname(nickname);
	chiChatConfig.setServer(server);
	chiChatConfig.setPort(port);
	chiChatConfig.setWorkgroup(workgroup);
	chiChatConfig.setConference(conference);
	chiChatConfig.setTextSize(textSize);

    }

    //
    // initialise the drawables
    //
    private void configureDrawables() {
	conferenceChatDrawable = getResources().getDrawable(R.drawable.conference_chat_display);
	workgroupChatDrawable = getResources().getDrawable(R.drawable.workgroup_chat_display);
	statusChatDrawable = getResources().getDrawable(R.drawable.status_chat_display);

	workgroupColorDrawable = new ColorDrawable(
		getResources().getColor(R.color.workgroup_color));
	conferenceColorDrawable = new ColorDrawable(
		getResources().getColor(R.color.conference_color));
	statusColorDrawable = new ColorDrawable(
		getResources().getColor(R.color.status_color));
    }

    //
    // configure the action bar across the top
    //
    private void configureActionBar() {
        actionBar = getActionBar();
	View actionBarView = actionBar.getCustomView();
	actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);

	actionBar.setBackgroundDrawable(workgroupColorDrawable);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

  	configureDrawables();

        configureActionBar();

	//
	// NB:  need to fix this
	//
 	StrictMode.ThreadPolicy policy = 
		new StrictMode.ThreadPolicy.Builder().permitAll().build();
	StrictMode.setThreadPolicy(policy);

	//
	// initialise the smack android routines
	//
	smackAndroid = SmackAndroid.init(this);

        setContentView(R.layout.main);



        messageText = (EditText) findViewById(R.id.msg);
        conversationView = (EditText) findViewById(R.id.conversation);
	conversationView.setTextColor(getResources().getColor(R.color.text_color));

	scrollingMovementMethod = ScrollingMovementMethod.getInstance();
	conversationView.setMovementMethod(scrollingMovementMethod);

	initChiChatConfig(this); 
	setTextSize(chiChatConfig.getTextSize());
	if ( chiChatConfig.getUsername().equals("unknown") ) {
		//
		// if the username is "unknown", then the user
		// has never used this application.  have him
		// set up the settings
		//
		settings();
	}
	else {

		updateStatus("connecting to server");
		workGroupChat = new WorkGroupChat(chiChatConfig, this);
		ConnectionAsyncTask connectionAsyncTask = new ConnectionAsyncTask();
		connectionAsyncTask.doInBackground(this, workGroupChat);
	}

	/*
	updateStatus("creating gestures");
	GestureDetector gestureDetector = new GestureDetector( this, 
		new ChiGestureDetector(this) );
	updateStatus("gestures created");
	*/


    }

    public boolean onCreateOptionsMenu(Menu menu) {
	MenuInflater menuInflater = getMenuInflater();


	menuInflater.inflate(R.menu.actionmenu, menu);
	menuInflater.inflate(R.menu.optionsmenu, menu);

	return super.onCreateOptionsMenu(menu);
    }

    public boolean onOptionsItemSelected(MenuItem item) {
	switch ( item.getItemId() ) {
		case R.id.logout:
			logout();
			return true;
		case R.id.reconnect:
			reconnect();
			return true;
		case R.id.settings:
			settings();
			return true;
		case R.id.status:
			show_status();
			return true;
        }
	return super.onOptionsItemSelected(item);
    }

    public void updateStatus(String st) {
	growingStatusConversation.append(st + "\n");
	if ( groupChatShowing == null ) {
		conversationView.setText(growingStatusConversation);
		conversationView.setSelection(growingStatusConversation.length());
	}

	/*
	Intent intent = new Intent();
	intent.putExtra("message", st);
	startActivityForResult(intent, 40);
	*/
    }


    //
    // add a line to the growing conversation
    //
    public void updateConversation(String from, String st, boolean groupChat) {
	try {
		status=status.concat("from - " + from);
		if ( groupChat ) {
			growingGroupConversation.append(/*"2-" +*/ from + ": " + st + "\n");
			if ( !groupChatShowing ) {
			}
		}
		else {
			if ( !from.equals(chiChatConfig.getNickname() )  ) {
				from = chiChatConfig.getWorkgroup();
			}
			growingPrivateConversation.append(/*"1-" +*/ from + ": " + st + "\n");
			if ( groupChatShowing ) {
		        }
		}
	

		Intent intent = new Intent();
		intent.putExtra("message", st);
		startActivityForResult(intent, 30);
	}
	catch ( Throwable t ) {
		activityResults = "th " + t;
	}
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
	try {
		activityResults = new String(" request " + requestCode + 
				" result " + resultCode + " intent " + data + " groupChatShowing " + 
				groupChatShowing);
		if ( requestCode == 30 ) {
			if ( groupChatShowing != null ) {
				if ( groupChatShowing ) {
					conversationView.setText(growingGroupConversation + "\n");
					conversationView.setSelection(growingGroupConversation.length());
				}
				else {
					conversationView.setText(growingPrivateConversation + "\n");
					conversationView.setSelection(growingPrivateConversation.length());
				}
			}
			else { 
				conversationView.setText(growingStatusConversation);
				conversationView.setSelection(growingStatusConversation.length());
			}
		}
	}
	catch ( Throwable t) {
		activityResults = new String("Th " + t);
	}
    }

    public void group_chat() {
	conversationView.setText(growingGroupConversation);
	conversationView.setSelection(growingGroupConversation.length());
	conversationView.setBackgroundDrawable(conferenceChatDrawable);
	groupChatShowing = true;
	//actionBar.setBackgroundDrawable(conferenceColorDrawable);
	messageText.setHint("type in your message");
        messageText.setEnabled(true);
    }

    //
    // called from action menu
    //
    public void group_chat(MenuItem menuItem) {
	group_chat();
    }

    //
    // called from Button
    //
    public void group_chat(View view) {
	group_chat();
    }

    public void private_chat() {
	conversationView.setText(growingPrivateConversation);
	conversationView.setSelection(growingPrivateConversation.length());
	conversationView.setBackgroundDrawable(workgroupChatDrawable);
	groupChatShowing = false;
	//actionBar.setBackgroundDrawable(workgroupColorDrawable);
	messageText.setHint("type in your message");
        messageText.setEnabled(true);
    }

    public void private_chat(MenuItem menuItem) {
	private_chat();
    }

    public void private_chat(View view) {
	private_chat();
    }

    public void show_status() {
	conversationView.setText(growingStatusConversation);
	conversationView.setSelection(growingStatusConversation.length());
	conversationView.setBackgroundDrawable(statusChatDrawable);
	groupChatShowing = null;
	//actionBar.setBackgroundDrawable(statusColorDrawable);
	messageText.setHint("select Private Chat or Group Chat");
        messageText.setEnabled(false);
    }

    public void show_status(MenuItem menuItem) {
	show_status();
    }

    public void show_status(View view) {
	show_status();
	
    }

    public void send(MenuItem menuItem) {
	send( (View) null);
    }

    public void send(View view) {
	if ( !messageText.getText().toString().trim().equals("") ) {
		workGroupChat.sendMessage(messageText.getText().toString(), groupChatShowing);
		messageText.setText("");
		String status = workGroupChat.getStatus();
	}
    }

    public void logout() {
	updateStatus("logged out");
	workGroupChat.disconnect();
    }

    public void reconnect() {
	growingGroupConversation = new StringBuilder();
	growingPrivateConversation = new StringBuilder();
	conversationView.setText("");
	initChiChatConfig(this);  
	workGroupChat = new WorkGroupChat(chiChatConfig, this);
	ConnectionAsyncTask connectionAsyncTask = new ConnectionAsyncTask();
	connectionAsyncTask.doInBackground(this, workGroupChat);
    }

    public void settings() {
	String status = "settings";
	try {
		
		//ChiPreferences chiPreferences = new ChiPreferences();
		//Intent intent = new Intent(this, chiPreferences.getClass());
		Intent intent = new Intent(this, ChiPreferences.class);
		startActivity(intent);
	}
	catch (Throwable t) {
		status = "settings throws " + t;
	}
	
    }

    public void gesture(String st) {
	updateStatus(st);
    }

}

class ChiGestureDetector extends GestureDetector.SimpleOnGestureListener {

    Chi chi = null;

    public ChiGestureDetector(Chi chi) {
	this.chi = chi;
    }

    public boolean onDoubleTap(MotionEvent e){
        chi.gesture("onDoubleTap");
    	return true;
    }

    public boolean onDoubleTapEvent(MotionEvent e){
        chi.gesture("onDoubleTapEvent");
    	return true;
    }

    public boolean onDown(MotionEvent e){
        chi.gesture("onDown");
    	return true;
    }

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
        chi.gesture("onFling");
    	return true;
    }

    public void onLongPress(MotionEvent e){
        chi.gesture("onLongPress");
    }

    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
        chi.gesture("onScroll");
    	return true;
    }

    public void onShowPress(MotionEvent e){
        chi.gesture("onShowPress");
    }

    public boolean onSingleTapConfirmed(MotionEvent e){
        chi.gesture("onSingleTapConfirmed");
    	return true;
    }

    public boolean onSingleTapUp(MotionEvent e){
        chi.gesture("onSingleTapUp");
    	return true;
    }


}

class ConnectionAsyncTask extends AsyncTask<Object, String, String> {

	Chi chi = null;
	WorkGroupChat workGroupChat = null;

@Override
protected String doInBackground(Object... params) {
	chi = (Chi) params[0];
	workGroupChat = (WorkGroupChat) params[1];
	try {
		chi.updateStatus("trying to login");
		if ( workGroupChat.login() ) {
			chi.updateStatus("trying to join groups");
			workGroupChat.joinWorkgroupAndConference();
			chi.updateStatus("sent request to join groups");
		}
		else {
			chi.updateStatus("could not login");
			chi.updateStatus(workGroupChat.getStatus());
		}
	}
	catch ( Throwable t ) {
		chi.updateStatus("ConnectionAsyncTask throwing " + t);
	}
	return "finished";
}

}

